/*
 * Copyright (C) 2017 Pingan, Inc. All Rights Reserved.
 */

package com.pingan.haofang.searchcloud.web.query;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.pingan.haofang.searchcloud.api.IndexRowData;
import com.pingan.haofang.searchcloud.api.query.parser.exception.SqlParseException;
import com.pingan.haofang.searchcloud.api.search.form.SqlForm;
import com.pingan.haofang.searchcloud.api.search.validator.SqlFormValidator;
import com.pingan.haofang.searchcloud.common.constants.WebConstants;
import com.pingan.haofang.searchcloud.common.exception.SystemException;
import com.pingan.haofang.searchcloud.common.validator.annotation.Valid;
import com.pingan.haofang.searchcloud.index.dto.SqlExplainDTO;
import com.pingan.haofang.searchcloud.index.dto.SqlResultDTO;
import com.pingan.haofang.searchcloud.index.service.SearchService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * 查询controller
 *
 * @author zhangbi617
 * @date 16/05/2017
 */
@RestController
@RequestMapping(value = WebConstants.WEB_PREFIX + "/sql")
@Api(tags = "Index.Query", description = "索引数据查询接口")
public class QueryController {

    @Autowired
    private SearchService searchService;

    private static final String EXPLAIN = "explain";

    /**
     * 管理端的SQL查询
     *
     * @param sql
     * @return
     */
    @RequestMapping(value = "/select", method = RequestMethod.POST)
    @Valid(SqlFormValidator.class)
    @ApiOperation("SQL Select查询")
    public SqlResultDTO postSelect(@RequestBody SqlForm form) {
        String sql = form.getSql();
        if (StringUtils.containsIgnoreCase(sql, EXPLAIN)) {
            String newSqlStr = StringUtils.replaceOnce(sql, EXPLAIN, "")
                    .replace(EXPLAIN.toUpperCase(), "");

            SqlForm newSqlForm = new SqlForm();
            newSqlForm.setSql(newSqlStr);
            return toSqlResultDTO(explain(newSqlForm));
        }
        try{
            return searchService.query(sql);
        } catch (SystemException e) {
            throw e;
        } catch (SqlParseException e) {
            throw new SystemException("search.sql.illegal", new Object[] { e.getMessage() }, e);
        } catch (Exception e) {
            throw new SystemException(e.getMessage() ,e);
        }
        
    }

    private SqlResultDTO toSqlResultDTO(SqlExplainDTO explainDTO) {
        List<IndexRowData> rowDatas = new ArrayList<IndexRowData>();
        BeanMap map = new BeanMap(explainDTO);
        for (Map.Entry<Object, Object> entry : map.entrySet()) {
            String key = entry.getKey().toString();
            if ("class".equalsIgnoreCase(key)) {
                continue;
            }
            if (null != entry.getValue()) {
                IndexRowData rowData = new IndexRowData();
                rowData.build("ExplainKey", key);
                rowData.build("ExplainInfo", entry.getValue());
                rowDatas.add(rowData);
            }

        }
        SqlResultDTO sqlResultDTO = new SqlResultDTO();
        sqlResultDTO.setResult(rowDatas);
        sqlResultDTO.setTotalFound(1L);
        sqlResultDTO.setResultSize(1L);
        return sqlResultDTO;
    }

    @RequestMapping(value = "/explain", method = RequestMethod.POST)
    @ApiOperation("SQL执行计划查询")
    public SqlExplainDTO explain(@RequestBody SqlForm sql) {
        return searchService.explain(sql.getSql());
    }
    
}
